﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;

namespace ServerControl1
{
    [DefaultProperty("Text")]
    [ToolboxData("<{0}:Thermometer runat=server></{0}:Thermometer>")]
    public class Thermometer : WebControl
    {
        [Bindable(true)]
        [Category("Appearance")]
        [DefaultValue("")]
        [Localizable(true)]
        public String Starts
        {
            get
            {
                String s = (String)ViewState["Starts"];
                return ((s == null) ? String.Empty : s);
            }
            set
            {
                ViewState["Starts"] = value;
            }
        }
        [Bindable(true)]
        [Category("Appearance")]
        [DefaultValue("")]
        [Localizable(true)]
        public String Ends
        {
            get
            {
                String s = (String)ViewState["Ends"];
                return ((s == null) ? String.Empty : s);
            }
            set
            {
                ViewState["Ends"] = value;
            }
        }
        [Bindable(true)]
        [Category("Appearance")]
        [DefaultValue("")]
        [Localizable(true)]
        public String Colors
        {
            get
            {
                String s = (String)ViewState["Colors"];
                return ((s == null) ? String.Empty : s);
            }
            set
            {
                ViewState["Colors"] = value;
            }
        }
        [Bindable(true)]
        [Category("Appearance")]
        [DefaultValue("")]
        [Localizable(true)]
        public int Control_Height
        {
            get
            {
                int s = (Int32)ViewState["Control_Height"];
                return ((s == null) ? 0 : s);
            }
            set
            {
                ViewState["Control_Height"] = value;
            }
        }
        [Bindable(true)]
        [Category("Appearance")]
        [DefaultValue("")]
        [Localizable(true)]
        public int No_Of_Markings
        {
            get
            {
                int s = (Int32)ViewState["No_Of_Markings"];
                return ((s == null) ? 0 : s);
            }
            set
            {
                ViewState["No_Of_Markings"] = value;
            }
        }
        [Bindable(true)]
        [Category("Appearance")]
        [DefaultValue("")]
        [Localizable(true)]
        public Decimal Scale_Start
        {
            get
            {
                Decimal s = (Decimal)ViewState["Scale_Start"];
                return ((s == null) ? 0 : s);
            }
            set
            {
                ViewState["Scale_Start"] = value;
            }
        }
        [Bindable(true)]
        [Category("Appearance")]
        [DefaultValue("")]
        [Localizable(true)]
        public Decimal Scale_End
        {
            get
            {
                Decimal s = (Decimal)ViewState["Scale_End"];
                return ((s == null) ? 0 : s);
            }
            set
            {
                ViewState["Scale_End"] = value;
            }
        }
        [Bindable(true)]
        [Category("Appearance")]
        [DefaultValue("")]
        [Localizable(true)]
        public Decimal LineMark
        {
            get
            {
                Decimal s = (Decimal)ViewState["LineMark"];
                return ((s == null) ? 0 : s);
            }
            set
            {
                ViewState["LineMark"] = value;
            }
        }
        [Bindable(true)]
        [Category("Appearance")]
        [DefaultValue("")]
        [Localizable(true)]
        public int thermo_width
        {
            get
            {
                int s = (Int32)ViewState["thermo_width"];
                return ((s == null) ? 0 : s);
            }
            set
            {
                ViewState["thermo_width"] = value;
            }
        }

        private Dictionary<String, List<HTMLDivTemplate>> controlStructure = new Dictionary<string, List<HTMLDivTemplate>>();
        protected override void OnPreRender(EventArgs e)
        {
            // Add style sheet to parent page
            string cssUrl = Page.ClientScript.GetWebResourceUrl(this.GetType(), "ServerControl1.Thermometer.css");
            AddResource("thermometer_base.png");
            AddResource("thermometer_cap.png");
            AddResource("bar_blue_slice.jpg");
            AddResource("bar_dark-blue_slice.jpg");
            AddResource("bar_green_slice.jpg");
            AddResource("bar_grey_slice.jpg");
            AddResource("bar_red_slice.jpg");
            AddResource("thermometer_middle-slice.jpg");
            AddResource("thermometer_top.jpg");

            HtmlLink cssLink = new HtmlLink();
            cssLink.Href = cssUrl;
            cssLink.Attributes.Add("rel", "stylesheet");
            cssLink.Attributes.Add("type", "text/css");
            this.Page.Header.Controls.Add(cssLink);
            base.OnPreRender(e);
        }
        private void AddResource(String Path)
        {
            String ResourceURL = Page.ClientScript.GetWebResourceUrl(this.GetType(), "ServerControl1." + Path);
        }
        protected override void RenderContents(HtmlTextWriter output)
        {

            No_Of_Markings--;
            //Scale height is Control height - ( height of the bulb and top of the thermometer)
            int ThermoTop_height = 13;
            int ThermoBulb_height = 34;
            Decimal Scale_Height;
            Decimal Marking_Height;
            int Marking_Thickness = 1;
            Decimal Scale_Per_Mark;
            int Thickness = 1;
            Decimal ThermoLabelHeight = 34;
            Decimal Thermo_bulbheight = 34;
            Scale_Height = Control_Height - (ThermoBulb_height + ThermoTop_height);
            Marking_Height = Scale_Height / No_Of_Markings;
            Scale_Per_Mark = (Scale_End - Scale_Start) / No_Of_Markings;
            output.AddAttribute(HtmlTextWriterAttribute.Id, "ThermoBox");
            output.AddAttribute(HtmlTextWriterAttribute.Class, "ThermoBox");
            output.AddStyleAttribute(HtmlTextWriterStyle.Height, Control_Height.ToString());
            output.RenderBeginTag(HtmlTextWriterTag.Div);
            int ScaleTemp = 0;
            List<HTMLDivTemplate> ScaleTextElements = new List<HTMLDivTemplate>();
            for (Decimal i = Scale_End; i >= Scale_Start; i -= (Scale_End - Scale_Start) / No_Of_Markings)
            {
                ScaleTextElements.Add(new HTMLDivTemplate { CssClass = "ScaleText", Top = ((Marking_Height) * ScaleTemp).ToString(), ID = "ScaleTextDiv_subDiv" + i.ToString(), InnerText = Convert.ToInt32(i).ToString() });
                ScaleTemp++;
            }

            ScaleTemp = 0;
            List<HTMLDivTemplate> ScaleElements = new List<HTMLDivTemplate>();
            for (int i = No_Of_Markings; i >= 0; i -= 1)
            {
                ScaleElements.Add(new HTMLDivTemplate { CssClass = "LongMarking", ID = "ScaleDiv_Longdiv" + i.ToString(), Top = Convert.ToDecimal((ScaleTemp) * (Marking_Height)).ToString(), Height = Convert.ToDecimal(Marking_Height * .50m - Marking_Thickness).ToString() });
                if (i > 0)
                {
                    ScaleElements.Add(new HTMLDivTemplate { CssClass = "ShortMarking", ID = "ScaleDiv_shortdiv" + i.ToString(), Top = Convert.ToDecimal((ScaleTemp) * (Marking_Height) + Marking_Height * .50m - Marking_Thickness).ToString(), Height = Convert.ToDecimal(Marking_Height * .50m - Marking_Thickness).ToString() });
                }
                ScaleTemp++;
            }


            List<HTMLDivTemplate> ThermoDivElements = new List<HTMLDivTemplate>();

            //Draw the Thermo meter Outline
            //Draw the top of the thermometer
            Decimal total_scaleHeight = Scale_Height + Convert.ToInt32(Marking_Height / 2) + 2 * No_Of_Markings * Thickness + Thickness;

            ThermoDivElements.Add(new HTMLDivTemplate { CssClass = "ThermoTopCovered", ID = "Thermo_Top" });
            ThermoDivElements.Add(new HTMLDivTemplate { CssClass = "ThermoBase", ID = "Thermo_Base", Top = (Scale_Height + ThermoTop_height).ToString() });
            ThermoDivElements.Add(new HTMLDivTemplate { CssClass = "WhiteBar", ID = "Thermo_Bar", Height = (Scale_Height).ToString(), Top = (ThermoTop_height).ToString() });

            //Draw the ranges
            String[] startMarks = Starts.Split(',');
            String[] endtMarks = Ends.Split(',');
            String[] colors = Colors.Split(',');
            //check if the above 3 arrays are of equal size TO-DO
            List<Bar> bars = new List<Bar>();
            int barcount = startMarks.Count();
            for (int i = 0; i < barcount; i++)
            {
                Bar b = new Bar { color = colors[i], start = Convert.ToDecimal(startMarks[i]), end = Convert.ToDecimal(endtMarks[i]) };
                bars.Add(b);
            }
            foreach (Bar b in bars)
            {
                Decimal BarRangeTop, BarRangeBottom, BarRangeHeight;
                //Deal with showing negative bars. this is not supported by the design of the thermometer. The thermometer is supposed to show data which can be depicted in the scale supported by Thermmometre
                //Now to show a positive scale and depict a negative value does not make any sense to thermomter.
                //Hence the requirement is to depict any negative value in the middle of the thermometer base bulb
                if (b.start < 0 || b.end < 0)
                {
                    BarRangeTop = BarRangeBottom = ThermoTop_height + Scale_Height + Thermo_bulbheight / 2;
                    BarRangeHeight = 0;
                }
                else
                {

                    BarRangeTop = Convert.ToDecimal((Scale_End - b.end) * Marking_Height / Scale_Per_Mark + ThermoTop_height);
                    BarRangeBottom = Convert.ToDecimal((Scale_End - b.start) * Marking_Height / Scale_Per_Mark + ThermoTop_height);
                    BarRangeHeight = BarRangeBottom - BarRangeTop;
                }

                Decimal BarRangeHeight_Pixelled = Math.Floor(BarRangeHeight) < BarRangeHeight ? Math.Floor(BarRangeHeight) + 1 : BarRangeHeight;
                ThermoDivElements.Add(new HTMLDivTemplate { CssClass = b.color, ID = "Thermo_Bar" + bars.IndexOf(b).ToString(), Height = (BarRangeHeight_Pixelled).ToString(), Top = (BarRangeTop).ToString() });

            }



            controlStructure.Add("ScaleTextDiv", ScaleTextElements);
            controlStructure.Add("ScaleDiv", ScaleElements);
            controlStructure.Add("ThermoDiv", ThermoDivElements);
            AddDivElement(output, new HTMLDivTemplate { ID = "ScaleTextDiv", CssClass = "ScaleTextDiv", Top = (ThermoTop_height - 5).ToString() });
            AddDivElement(output, new HTMLDivTemplate { ID = "ScaleDiv", CssClass = "ScaleDiv", Top = ThermoTop_height.ToString(), Height = Scale_Height.ToString() });
            AddDivElement(output, new HTMLDivTemplate { ID = "TargetMarkerDiv", CssClass = "TargetMarkerDiv" });
            AddDivElement(output, new HTMLDivTemplate { ID = "ThermoDiv", CssClass = "ThermoDiv" });
            AddDivElement(output, new HTMLDivTemplate { ID = "LabelDiv", CssClass = "LabelDiv" });
            output.RenderEndTag();





        }
        private void AddDivElement(HtmlTextWriter output, HTMLDivTemplate h)
        {
            output.AddAttribute(HtmlTextWriterAttribute.Id, h.ID);
            output.AddAttribute(HtmlTextWriterAttribute.Class, h.CssClass);

            if (h.Top != null) output.AddStyleAttribute(HtmlTextWriterStyle.Top, h.Top + "px");
            if (h.Height != null) output.AddStyleAttribute(HtmlTextWriterStyle.Height, h.Height + "px");
            if (h.Width != null) output.AddStyleAttribute(HtmlTextWriterStyle.Width, h.Width + "px");
            if (h.Left != null) output.AddStyleAttribute(HtmlTextWriterStyle.Left, h.Left + "px");
            output.RenderBeginTag(HtmlTextWriterTag.Div);
            if (h.InnerText != null) output.Write(h.InnerText);
            //Render the children from the control structure dictionary
            if (controlStructure.ContainsKey(h.ID))
            {
                foreach (HTMLDivTemplate hd in controlStructure[h.ID])
                {
                    AddDivElement(output, hd);
                }
            }

            output.RenderEndTag();
        }
    }

    public class HTMLDivTemplate
    {
        public String Top, Height, Width, Left;
        public string CssClass, ID, InnerText;
    }

    public class Bar
    {
        public decimal start, end;
        public string color;
    }

}
